/**
 * WebSocket连接池管理器 - Phase 2 性能优化
 * 管理多个数据源的WebSocket连接，实现连接复用、负载均衡和故障转移
 */

import { globalPerformanceMonitor } from './performance-monitor';

// 连接状态枚举
export enum ConnectionState {
  DISCONNECTED = 'disconnected',
  CONNECTING = 'connecting',
  CONNECTED = 'connected',
  RECONNECTING = 'reconnecting',
  FAILED = 'failed'
}

// WebSocket连接配置
export interface WebSocketConfig {
  url: string;
  protocols?: string | string[];
  reconnectInterval?: number; // 重连间隔(ms)
  maxReconnectAttempts?: number; // 最大重连次数
  heartbeatInterval?: number; // 心跳间隔(ms)
  connectionTimeout?: number; // 连接超时(ms)
  maxMessageQueueSize?: number; // 最大消息队列大小
}

// 连接池配置
export interface PoolConfig {
  maxConnections: number; // 最大连接数
  connectionTimeout: number; // 连接超时时间
  healthCheckInterval: number; // 健康检查间隔
  loadBalancingStrategy: 'round-robin' | 'least-connections' | 'random'; // 负载均衡策略
  retryPolicy: {
    maxRetries: number;
    baseDelay: number;
    maxDelay: number;
    backoffMultiplier: number;
  };
}

// 连接信息
export interface ConnectionInfo {
  id: string;
  url: string;
  websocket: WebSocket | null;
  state: ConnectionState;
  lastConnected: number;
  lastPing: number;
  reconnectAttempts: number;
  activeSubscribers: number;
  messagesSent: number;
  messagesReceived: number;
  messageQueue: any[];
  config: WebSocketConfig;
}

// 消息处理器类型
export type MessageHandler = (data: any, connectionId: string) => void;
export type StateChangeHandler = (connectionId: string, state: ConnectionState) => void;

// 默认配置
const DEFAULT_WEBSOCKET_CONFIG: Required<WebSocketConfig> = {
  url: '',
  protocols: [],
  reconnectInterval: 3000,
  maxReconnectAttempts: 5,
  heartbeatInterval: 30000,
  connectionTimeout: 10000,
  maxMessageQueueSize: 100
};

const DEFAULT_POOL_CONFIG: PoolConfig = {
  maxConnections: 10,
  connectionTimeout: 10000,
  healthCheckInterval: 60000,
  loadBalancingStrategy: 'round-robin',
  retryPolicy: {
    maxRetries: 3,
    baseDelay: 1000,
    maxDelay: 30000,
    backoffMultiplier: 2
  }
};

/**
 * WebSocket连接池管理器类
 */
export class WebSocketPool {
  private connections = new Map<string, ConnectionInfo>();
  private messageHandlers: MessageHandler[] = [];
  private stateChangeHandlers: StateChangeHandler[] = [];
  private poolConfig: PoolConfig;
  private roundRobinIndex = 0;
  private healthCheckTimer: number | null = null;

  constructor(config: Partial<PoolConfig> = {}) {
    this.poolConfig = { ...DEFAULT_POOL_CONFIG, ...config };
    this.startHealthCheck();
  }

  /**
   * 生成连接ID
   */
  private generateConnectionId(): string {
    return 'ws_' + Math.random().toString(36).substr(2, 9) + '_' + Date.now();
  }

  /**
   * 创建连接
   */
  async createConnection(config: WebSocketConfig): Promise<string> {
    if (this.connections.size >= this.poolConfig.maxConnections) {
      throw new Error(`已达到最大连接数限制: ${this.poolConfig.maxConnections}`);
    }

    const connectionId = this.generateConnectionId();
    const fullConfig = { ...DEFAULT_WEBSOCKET_CONFIG, ...config };

    const connectionInfo: ConnectionInfo = {
      id: connectionId,
      url: fullConfig.url,
      websocket: null,
      state: ConnectionState.DISCONNECTED,
      lastConnected: 0,
      lastPing: 0,
      reconnectAttempts: 0,
      activeSubscribers: 0,
      messagesSent: 0,
      messagesReceived: 0,
      messageQueue: [],
      config: fullConfig
    };

    this.connections.set(connectionId, connectionInfo);

    try {
      await this.connect(connectionId);
      globalPerformanceMonitor.recordEvent({
        type: 'websocket-connection-created',
        data: { connectionId, url: fullConfig.url }
      });
      return connectionId;
    } catch (error) {
      this.connections.delete(connectionId);
      throw error;
    }
  }

  /**
   * 连接到WebSocket服务器
   */
  private async connect(connectionId: string): Promise<void> {
    const connection = this.connections.get(connectionId);
    if (!connection) {
      throw new Error(`连接不存在: ${connectionId}`);
    }

    if (
      connection.state === ConnectionState.CONNECTED ||
      connection.state === ConnectionState.CONNECTING
    ) {
      return;
    }

    connection.state = ConnectionState.CONNECTING;
    this.notifyStateChange(connectionId, ConnectionState.CONNECTING);

    return new Promise((resolve, reject) => {
      const ws = new WebSocket(connection.config.url, connection.config.protocols);
      connection.websocket = ws;

      const connectTimeout = setTimeout(() => {
        ws.close();
        connection.state = ConnectionState.FAILED;
        this.notifyStateChange(connectionId, ConnectionState.FAILED);
        reject(new Error('连接超时'));
      }, connection.config.connectionTimeout);

      ws.onopen = () => {
        clearTimeout(connectTimeout);
        connection.state = ConnectionState.CONNECTED;
        connection.lastConnected = Date.now();
        connection.reconnectAttempts = 0;

        this.notifyStateChange(connectionId, ConnectionState.CONNECTED);
        this.startHeartbeat(connectionId);
        this.processMessageQueue(connectionId);

        resolve();
      };

      ws.onmessage = (event) => {
        connection.messagesReceived++;
        try {
          const data = JSON.parse(event.data);
          this.handleMessage(data, connectionId);
        } catch (error) {
          console.error('消息解析失败:', error, event.data);
        }
      };

      ws.onclose = (event) => {
        clearTimeout(connectTimeout);
        this.stopHeartbeat(connectionId);

        if (connection.state === ConnectionState.CONNECTED) {
          // 意外断开，尝试重连
          this.scheduleReconnect(connectionId);
        } else {
          connection.state = ConnectionState.DISCONNECTED;
          this.notifyStateChange(connectionId, ConnectionState.DISCONNECTED);
        }
      };

      ws.onerror = (error) => {
        clearTimeout(connectTimeout);
        console.error('WebSocket错误:', error);
        connection.state = ConnectionState.FAILED;
        this.notifyStateChange(connectionId, ConnectionState.FAILED);

        if (connection.state === ConnectionState.CONNECTING) {
          reject(error);
        }
      };
    });
  }

  /**
   * 安排重连
   */
  private scheduleReconnect(connectionId: string): void {
    const connection = this.connections.get(connectionId);
    if (!connection) return;

    if (connection.reconnectAttempts >= connection.config.maxReconnectAttempts) {
      connection.state = ConnectionState.FAILED;
      this.notifyStateChange(connectionId, ConnectionState.FAILED);
      return;
    }

    connection.state = ConnectionState.RECONNECTING;
    connection.reconnectAttempts++;
    this.notifyStateChange(connectionId, ConnectionState.RECONNECTING);

    const delay = Math.min(
      connection.config.reconnectInterval * Math.pow(2, connection.reconnectAttempts - 1),
      30000 // 最大30秒
    );

    setTimeout(() => {
      this.connect(connectionId).catch((error) => {
        console.error('重连失败:', error);
        this.scheduleReconnect(connectionId);
      });
    }, delay);
  }

  /**
   * 开始心跳检测
   */
  private startHeartbeat(connectionId: string): void {
    const connection = this.connections.get(connectionId);
    if (!connection) return;

    const heartbeatTimer = setInterval(() => {
      if (connection.websocket?.readyState === WebSocket.OPEN) {
        const pingMessage = { type: 'ping', timestamp: Date.now() };
        this.sendMessage(connectionId, pingMessage);
        connection.lastPing = Date.now();
      }
    }, connection.config.heartbeatInterval);

    // 存储定时器引用用于清理
    connection._heartbeatTimer = heartbeatTimer;
  }

  /**
   * 停止心跳检测
   */
  private stopHeartbeat(connectionId: string): void {
    const connection = this.connections.get(connectionId);
    if (!connection) return;

    const heartbeatTimer = connection._heartbeatTimer;
    if (heartbeatTimer) {
      clearInterval(heartbeatTimer);
      connection._heartbeatTimer = undefined;
    }
  }

  /**
   * 处理消息队列
   */
  private processMessageQueue(connectionId: string): void {
    const connection = this.connections.get(connectionId);
    if (!connection || connection.state !== ConnectionState.CONNECTED) return;

    while (connection.messageQueue.length > 0) {
      const message = connection.messageQueue.shift();
      if (message) {
        this.sendMessage(connectionId, message, false);
      }
    }
  }

  /**
   * 发送消息
   */
  sendMessage(connectionId: string, message: any, queueIfDisconnected: boolean = true): boolean {
    const connection = this.connections.get(connectionId);
    if (!connection) return false;

    if (connection.state !== ConnectionState.CONNECTED) {
      if (
        queueIfDisconnected &&
        connection.messageQueue.length < connection.config.maxMessageQueueSize
      ) {
        connection.messageQueue.push(message);
        return true;
      }
      return false;
    }

    try {
      const messageStr = JSON.stringify(message);
      connection.websocket!.send(messageStr);
      connection.messagesSent++;
      return true;
    } catch (error) {
      console.error('发送消息失败:', error);
      return false;
    }
  }

  /**
   * 广播消息到所有连接
   */
  broadcast(message: any): number {
    let successCount = 0;

    for (const connection of this.connections.values()) {
      if (this.sendMessage(connection.id, message, false)) {
        successCount++;
      }
    }

    return successCount;
  }

  /**
   * 根据负载均衡策略选择连接
   */
  selectConnection(): string | null {
    const availableConnections = Array.from(this.connections.values()).filter(
      (conn) => conn.state === ConnectionState.CONNECTED
    );

    if (availableConnections.length === 0) return null;

    switch (this.poolConfig.loadBalancingStrategy) {
      case 'round-robin':
        const selectedIndex = this.roundRobinIndex % availableConnections.length;
        this.roundRobinIndex++;
        return availableConnections[selectedIndex].id;

      case 'least-connections':
        return availableConnections.reduce((prev, current) =>
          prev.activeSubscribers <= current.activeSubscribers ? prev : current
        ).id;

      case 'random':
        const randomIndex = Math.floor(Math.random() * availableConnections.length);
        return availableConnections[randomIndex].id;

      default:
        return availableConnections[0].id;
    }
  }

  /**
   * 处理收到的消息
   */
  private handleMessage(data: any, connectionId: string): void {
    this.messageHandlers.forEach((handler) => {
      try {
        handler(data, connectionId);
      } catch (error) {
        console.error('消息处理器执行失败:', error);
      }
    });
  }

  /**
   * 通知状态变化
   */
  private notifyStateChange(connectionId: string, state: ConnectionState): void {
    this.stateChangeHandlers.forEach((handler) => {
      try {
        handler(connectionId, state);
      } catch (error) {
        console.error('状态变化处理器执行失败:', error);
      }
    });
  }

  /**
   * 添加消息处理器
   */
  addMessageHandler(handler: MessageHandler): void {
    this.messageHandlers.push(handler);
  }

  /**
   * 移除消息处理器
   */
  removeMessageHandler(handler: MessageHandler): void {
    const index = this.messageHandlers.indexOf(handler);
    if (index > -1) {
      this.messageHandlers.splice(index, 1);
    }
  }

  /**
   * 添加状态变化处理器
   */
  addStateChangeHandler(handler: StateChangeHandler): void {
    this.stateChangeHandlers.push(handler);
  }

  /**
   * 移除状态变化处理器
   */
  removeStateChangeHandler(handler: StateChangeHandler): void {
    const index = this.stateChangeHandlers.indexOf(handler);
    if (index > -1) {
      this.stateChangeHandlers.splice(index, 1);
    }
  }

  /**
   * 关闭连接
   */
  closeConnection(connectionId: string): void {
    const connection = this.connections.get(connectionId);
    if (!connection) return;

    this.stopHeartbeat(connectionId);

    if (connection.websocket) {
      connection.websocket.close();
    }

    this.connections.delete(connectionId);

    globalPerformanceMonitor.recordEvent({
      type: 'websocket-connection-closed',
      data: { connectionId }
    });
  }

  /**
   * 关闭所有连接
   */
  closeAllConnections(): void {
    for (const connectionId of this.connections.keys()) {
      this.closeConnection(connectionId);
    }
  }

  /**
   * 开始健康检查
   */
  private startHealthCheck(): void {
    this.healthCheckTimer = window.setInterval(() => {
      this.performHealthCheck();
    }, this.poolConfig.healthCheckInterval);
  }

  /**
   * 执行健康检查
   */
  private performHealthCheck(): void {
    const now = Date.now();

    for (const connection of this.connections.values()) {
      // 检查连接是否长时间无响应
      if (connection.state === ConnectionState.CONNECTED) {
        const timeSinceLastPing = now - connection.lastPing;

        if (timeSinceLastPing > connection.config.heartbeatInterval * 3) {
          console.warn(`连接 ${connection.id} 心跳超时，尝试重连`);
          connection.websocket?.close();
        }
      }

      // 清理失败的连接
      if (connection.state === ConnectionState.FAILED && connection.activeSubscribers === 0) {
        this.closeConnection(connection.id);
      }
    }
  }

  /**
   * 获取连接池统计信息
   */
  getPoolStats() {
    const connections = Array.from(this.connections.values());

    const stats = {
      totalConnections: connections.length,
      connectedCount: connections.filter((c) => c.state === ConnectionState.CONNECTED).length,
      connectingCount: connections.filter((c) => c.state === ConnectionState.CONNECTING).length,
      reconnectingCount: connections.filter((c) => c.state === ConnectionState.RECONNECTING).length,
      failedCount: connections.filter((c) => c.state === ConnectionState.FAILED).length,
      totalMessagesSent: connections.reduce((sum, c) => sum + c.messagesSent, 0),
      totalMessagesReceived: connections.reduce((sum, c) => sum + c.messagesReceived, 0),
      activeSubscribers: connections.reduce((sum, c) => sum + c.activeSubscribers, 0),
      queuedMessages: connections.reduce((sum, c) => sum + c.messageQueue.length, 0),
      config: this.poolConfig
    };

    return stats;
  }

  /**
   * 获取连接详情
   */
  getConnectionDetails(): ConnectionInfo[] {
    return Array.from(this.connections.values()).map((conn) => ({
      ...conn,
      websocket: conn.websocket ? 'WebSocket实例' : null
    })) as ConnectionInfo[];
  }

  /**
   * 销毁连接池
   */
  destroy(): void {
    if (this.healthCheckTimer) {
      clearInterval(this.healthCheckTimer);
      this.healthCheckTimer = null;
    }

    this.closeAllConnections();
    this.messageHandlers = [];
    this.stateChangeHandlers = [];
  }
}

// 全局WebSocket连接池实例
export const globalWebSocketPool = new WebSocketPool({
  maxConnections: 8,
  healthCheckInterval: 30000,
  loadBalancingStrategy: 'least-connections'
});

// 便捷函数
export const createConnection = (config: WebSocketConfig) => {
  return globalWebSocketPool.createConnection(config);
};

export const sendMessage = (connectionId: string, message: any) => {
  return globalWebSocketPool.sendMessage(connectionId, message);
};

export const broadcast = (message: any) => {
  return globalWebSocketPool.broadcast(message);
};

export const getPoolStats = () => {
  return globalWebSocketPool.getPoolStats();
};
